home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume6 / less2 / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  62.3 KB

  1. Subject:  v06i103:  New version of less (less2), Part02/02
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: seismo!lll-crg!csustan!casey
  6. Mod.sources: Volume 6, Issue 103
  7. Archive-name: less2/Part02
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create:
  14. #    makefile.sys5
  15. #    makefile.xen
  16. #    mkfuncs.awk
  17. #    n10-diff
  18. #    option.c
  19. #    output.c
  20. #    pager_patch.c
  21. #    position.c
  22. #    position.h
  23. #    prim.c
  24. #    prompt.c
  25. #    screen.c
  26. #    signal.c
  27. #    ttyin.c
  28. #    version.c
  29. export PATH; PATH=/bin:/usr/bin:$PATH
  30. if test -f 'makefile.sys5'
  31. then
  32.     echo shar: "will not over-write existing file 'makefile.sys5'"
  33. else
  34. cat << \SHAR_EOF > 'makefile.sys5'
  35. # Makefile for "less"
  36. #
  37. # Invoked as:
  38. #    make all
  39. #   or    make install
  40. # Plain "make" is equivalent to "make all".
  41. #
  42. # If you add or delete functions, remake funcs.h by doing:
  43. #    make newfuncs
  44. # This depends on the coding convention of function headers looking like:
  45. #    " \t public <function-type> \n <function-name> ( ... ) "
  46. #
  47. # Also provided:
  48. #    make lint    # Runs "lint" on all the sources.
  49. #    make clean    # Removes "less" and the .o files.
  50. #    make clobber    # Pretty much the same as make "clean".
  51. #
  52. #    make pager_patch        # makes PAGER environment variable
  53. #    make install_pager_patch    # catcher and installs it (see below)
  54.  
  55.  
  56. ##########################################################################
  57. # System-specific parameters
  58. ##########################################################################
  59.  
  60. # Define XENIX if running under XENIX 3.0
  61. XENIX = 0
  62.  
  63. # VOID is 1 if your C compiler supports the "void" type,
  64. # 0 if it does not.
  65. VOID = 1
  66.  
  67. # off_t is the type which lseek() returns.
  68. # It is also the type of lseek()'s second argument.
  69. off_t = long
  70.  
  71. # TERMIO is 1 if your system has /usr/include/termio.h.
  72. # This is normally the case for System 5.
  73. # If TERMIO is 0 your system must have /usr/include/sgtty.h.
  74. # This is normally the case for BSD.
  75. TERMIO = 1
  76.  
  77. # SIGSETMASK is 1 if your system has the sigsetmask() call.
  78. # This is normally the case only for BSD 4.2,
  79. # not for BSD 4.1 or System 5.
  80. SIGSETMASK = 0
  81.  
  82.  
  83. ##########################################################################
  84. # Optional and semi-optional features
  85. ##########################################################################
  86.  
  87. # REGCMP is 1 if your system has the regcmp() function.
  88. # This is normally the case for System 5.
  89. # RECOMP is 1 if your system has the re_comp() function.
  90. # This is normally the case for BSD.
  91. # If neither is 1, pattern matching is supported, but without metacharacters.
  92. REGCMP = 1
  93. RECOMP = 0
  94.  
  95. # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
  96. # (This is possible only if your system supplies the system() function.)
  97. SHELL_ESCAPE = 0
  98.  
  99. # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
  100. # (This is possible only if your system supplies the system() function.)
  101. # EDIT_PGM is the name of the (default) editor to be invoked.
  102. EDITOR = 0
  103. EDIT_PGM = /usr/ucb/vi
  104.  
  105. # parameters to "make install_pager_patch".  OLD_PAGER will be moved to
  106. # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
  107. # as OLD_PAGER.  This patch will allow you to set the environment variable
  108. # PAGER to specify your personal pager preference (is this a security hole?)
  109. OLD_PAGER = /usr/ucb/more
  110. OLD_PAGER_NEW_LOCATION = /usr/ucb/More
  111.  
  112. # ONLY_RETURN is 1 if you want RETURN to be the only input which
  113. # will continue past an error message.
  114. # Otherwise, any key will continue past an error message.
  115. ONLY_RETURN = 0
  116.  
  117.  
  118. ##########################################################################
  119. # Compilation environment.
  120. ##########################################################################
  121.  
  122. # LIBS is the list of libraries needed.
  123. LIBS = -lcurses -lPW
  124.  
  125. # INSTALL_LESS is a list of the public versions of less.
  126. # INSTALL_MAN is a list of the public versions of the manual page.
  127. INSTALL_LESS =    /usr/lbin/less
  128. INSTALL_MAN =    /usr/man/manl/less.l
  129.  
  130. # OPTIM is passed to the compiler and the loader.
  131. # It is normally "-O" but may be, for example, "-g".
  132. OPTIM = -O
  133.  
  134.  
  135. ##########################################################################
  136. # Files
  137. ##########################################################################
  138.  
  139. SRC1 =    main.c option.c prim.c 
  140. SRC2 =    ch.c position.c input.c output.c screen.c \
  141.     prompt.c line.c signal.c help.c ttyin.c command.c version.c
  142. SRC =    $(SRC1) $(SRC2)
  143. OBJ =    main.o option.o prim.o ch.o position.o input.o output.o screen.o \
  144.     prompt.o line.o signal.o help.o ttyin.o command.o version.o
  145.  
  146.  
  147. ##########################################################################
  148. # Rules
  149. ##########################################################################
  150.  
  151. DEFS =    "-DTERMIO=$(TERMIO)" \
  152.     "-DSIGSETMASK=$(SIGSETMASK)" \
  153.     "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
  154.     "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
  155.     "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
  156.     "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
  157.     "-DONLY_RETURN=$(ONLY_RETURN)" \
  158.     "-DXENIX=$(XENIX)" \
  159.     "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
  160.  
  161. CFLAGS = $(OPTIM) $(DEFS)
  162.  
  163.  
  164. all: less
  165.  
  166. less: $(OBJ)
  167.     cc $(OPTIM) -o less $(OBJ) $(LIBS)
  168.  
  169. install: install_man install_less
  170.  
  171. install_man: less.l
  172.     for f in $(INSTALL_MAN); do  rm -f $$f; cp less.l $$f;  done
  173.     touch install_man
  174.     
  175. install_less: less
  176.     for f in $(INSTALL_LESS); do  rm -f $$f; cp less $$f;  done
  177.     touch install_less
  178.  
  179. pager_patch: pager_patch.c
  180.     cc $(CFLAGS) -s -o pager_patch pager_patch.c
  181.  
  182. install_pager_patch: pager_patch
  183.     if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
  184.         mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
  185.         cp pager_patch $(OLD_PAGER); \
  186.     fi
  187.     touch install_pager_patch
  188.  
  189. $(OBJ): less.h funcs.h
  190.  
  191. lint:
  192.     lint -hp $(DEFS) $(SRC)
  193.  
  194. newfuncs:
  195.     mv funcs.h funcs.h.OLD
  196.     awk -f mkfuncs.awk $(SRC) >funcs.h
  197.  
  198. clean:
  199.     rm -f $(OBJ) less pager_patch
  200.  
  201. clobber:
  202.     rm -f *.o less pager_patch install_less install_man install_pager_patch
  203.  
  204. shar:
  205.     shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
  206.     shar -v $(SRC2) pager_patch.c > less.shar.b
  207. SHAR_EOF
  208. fi
  209. if test -f 'makefile.xen'
  210. then
  211.     echo shar: "will not over-write existing file 'makefile.xen'"
  212. else
  213. cat << \SHAR_EOF > 'makefile.xen'
  214. # Makefile for "less"
  215. #
  216. # Invoked as:
  217. #    make all
  218. #   or    make install
  219. # Plain "make" is equivalent to "make all".
  220. #
  221. # If you add or delete functions, remake funcs.h by doing:
  222. #    make newfuncs
  223. # This depends on the coding convention of function headers looking like:
  224. #    " \t public <function-type> \n <function-name> ( ... ) "
  225. #
  226. # Also provided:
  227. #    make lint    # Runs "lint" on all the sources.
  228. #    make clean    # Removes "less" and the .o files.
  229. #    make clobber    # Pretty much the same as make "clean".
  230. #
  231. #    make pager_patch        # makes PAGER environment variable
  232. #    make install_pager_patch    # catcher and installs it (see below)
  233.  
  234.  
  235. ##########################################################################
  236. # System-specific parameters
  237. ##########################################################################
  238.  
  239. # Define XENIX if running under XENIX 3.0
  240. XENIX = 1
  241.  
  242. # VOID is 1 if your C compiler supports the "void" type,
  243. # 0 if it does not.
  244. VOID = 1
  245.  
  246. # off_t is the type which lseek() returns.
  247. # It is also the type of lseek()'s second argument.
  248. off_t = long
  249.  
  250. # TERMIO is 1 if your system has /usr/include/termio.h.
  251. # This is normally the case for System 5.
  252. # If TERMIO is 0 your system must have /usr/include/sgtty.h.
  253. # This is normally the case for BSD.
  254. TERMIO = 1
  255.  
  256. # SIGSETMASK is 1 if your system has the sigsetmask() call.
  257. # This is normally the case only for BSD 4.2,
  258. # not for BSD 4.1 or System 5.
  259. SIGSETMASK = 0
  260.  
  261.  
  262. ##########################################################################
  263. # Optional and semi-optional features
  264. ##########################################################################
  265.  
  266. # REGCMP is 1 if your system has the regcmp() function.
  267. # This is normally the case for System 5.
  268. # RECOMP is 1 if your system has the re_comp() function.
  269. # This is normally the case for BSD.
  270. # If neither is 1, pattern matching is supported, but without metacharacters.
  271. REGCMP = 1
  272. RECOMP = 0
  273.  
  274. # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
  275. # (This is possible only if your system supplies the system() function.)
  276. SHELL_ESCAPE = 0
  277.  
  278. # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
  279. # (This is possible only if your system supplies the system() function.)
  280. # EDIT_PGM is the name of the (default) editor to be invoked.
  281. EDITOR = 0
  282. EDIT_PGM = /usr/ucb/vi
  283.  
  284. # parameters to "make install_pager_patch".  OLD_PAGER will be moved to
  285. # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
  286. # as OLD_PAGER.  This patch will allow you to set the environment variable
  287. # PAGER to specify your personal pager preference (is this a security hole?)
  288. OLD_PAGER = /usr/ucb/more
  289. OLD_PAGER_NEW_LOCATION = /usr/ucb/More
  290.  
  291. # ONLY_RETURN is 1 if you want RETURN to be the only input which
  292. # will continue past an error message.
  293. # Otherwise, any key will continue past an error message.
  294. ONLY_RETURN = 0
  295.  
  296.  
  297. ##########################################################################
  298. # Compilation environment.
  299. ##########################################################################
  300.  
  301. # LIBS is the list of libraries needed.
  302. LIBS = -lcurses -ltermlib
  303.  
  304. # INSTALL_LESS is a list of the public versions of less.
  305. # INSTALL_MAN is a list of the public versions of the manual page.
  306. INSTALL_LESS =    /usr/lbin/less
  307. INSTALL_MAN =    /usr/man/manl/less.l
  308.  
  309. # OPTIM is passed to the compiler and the loader.
  310. # It is normally "-O" but may be, for example, "-g".
  311. OPTIM = -O
  312.  
  313.  
  314. ##########################################################################
  315. # Files
  316. ##########################################################################
  317.  
  318. SRC1 =    main.c option.c prim.c 
  319. SRC2 =    ch.c position.c input.c output.c screen.c \
  320.     prompt.c line.c signal.c help.c ttyin.c command.c version.c
  321. SRC =    $(SRC1) $(SRC2)
  322. OBJ =    main.o option.o prim.o ch.o position.o input.o output.o screen.o \
  323.     prompt.o line.o signal.o help.o ttyin.o command.o version.o
  324.  
  325.  
  326. ##########################################################################
  327. # Rules
  328. ##########################################################################
  329.  
  330. DEFS =    "-DTERMIO=$(TERMIO)" \
  331.     "-DSIGSETMASK=$(SIGSETMASK)" \
  332.     "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
  333.     "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
  334.     "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
  335.     "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
  336.     "-DONLY_RETURN=$(ONLY_RETURN)" \
  337.     "-DXENIX=$(XENIX)" \
  338.     "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
  339.  
  340. CFLAGS = $(OPTIM) $(DEFS)
  341.  
  342.  
  343. all: less
  344.  
  345. less: $(OBJ)
  346.     cc $(OPTIM) -o less $(OBJ) $(LIBS)
  347.  
  348. install: install_man install_less
  349.  
  350. install_man: less.l
  351.     for f in $(INSTALL_MAN); do  rm -f $$f; cp less.l $$f;  done
  352.     touch install_man
  353.     
  354. install_less: less
  355.     for f in $(INSTALL_LESS); do  rm -f $$f; cp less $$f;  done
  356.     touch install_less
  357.  
  358. pager_patch: pager_patch.c
  359.     cc $(CFLAGS) -s -o pager_patch pager_patch.c
  360.  
  361. install_pager_patch: pager_patch
  362.     if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
  363.         mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
  364.         cp pager_patch $(OLD_PAGER); \
  365.     fi
  366.     touch install_pager_patch
  367.  
  368. $(OBJ): less.h funcs.h
  369.  
  370. lint:
  371.     lint -hp $(DEFS) $(SRC)
  372.  
  373. newfuncs:
  374.     mv funcs.h funcs.h.OLD
  375.     awk -f mkfuncs.awk $(SRC) >funcs.h
  376.  
  377. clean:
  378.     rm -f $(OBJ) less pager_patch
  379.  
  380. clobber:
  381.     rm -f *.o less pager_patch install_less install_man install_pager_patch
  382.  
  383. shar:
  384.     shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
  385.     shar -v $(SRC2) pager_patch.c > less.shar.b
  386. SHAR_EOF
  387. fi
  388. if test -f 'mkfuncs.awk'
  389. then
  390.     echo shar: "will not over-write existing file 'mkfuncs.awk'"
  391. else
  392. cat << \SHAR_EOF > 'mkfuncs.awk'
  393. BEGIN { FS="("; state = 0 }
  394.  
  395. /^    public/ { ftype = $0; state = 1 }
  396.  
  397. { if (state == 1)
  398.     state = 2
  399.   else if (state == 2)
  400.     { print ftype,$1,"();"; state = 0 }
  401. }
  402. SHAR_EOF
  403. fi
  404. if test -f 'n10-diff'
  405. then
  406.     echo shar: "will not over-write existing file 'n10-diff'"
  407. else
  408. cat << \SHAR_EOF > 'n10-diff'
  409. *** n10-old.c    Sun May  4 01:45:06 1986
  410. --- n10.c    Mon Jul 14 12:27:54 1986
  411. ***************
  412. *** 137,151
  413.       if(*codep && (esc || lead))move();
  414.       esct += w;
  415.       if(i&074000)xfont = (i>>9) & 03;
  416. !     if(*t.bdon & 0377){
  417. !         if(!bdmode && (xfont == 2)){
  418. !             oputs(t.bdon);
  419. !             bdmode++;
  420. !         }
  421. !         if(bdmode && (xfont != 2)){
  422. !             oputs(t.bdoff);
  423. !             bdmode = 0;
  424. !         }
  425.       }
  426.       if(xfont == ulfont){
  427.           for(k=w/t.Char;k>0;k--)oput('_');
  428.  
  429. --- 137,145 -----
  430.       if(*codep && (esc || lead))move();
  431.       esct += w;
  432.       if(i&074000)xfont = (i>>9) & 03;
  433. !     if(!bdmode && (xfont == 2)){
  434. !         if(*t.bdon & 0377)oputs(t.bdon);
  435. !         bdmode++;
  436.       }
  437.       if(bdmode && (xfont != 2)){
  438.           if(*t.bdoff & 0377)oputs(t.bdoff);
  439. ***************
  440. *** 147,152
  441.               bdmode = 0;
  442.           }
  443.       }
  444.       if(xfont == ulfont){
  445.           for(k=w/t.Char;k>0;k--)oput('_');
  446.           for(k=w/t.Char;k>0;k--)oput('\b');
  447.  
  448. --- 141,150 -----
  449.           if(*t.bdon & 0377)oputs(t.bdon);
  450.           bdmode++;
  451.       }
  452. +     if(bdmode && (xfont != 2)){
  453. +         if(*t.bdoff & 0377)oputs(t.bdoff);
  454. +         bdmode = 0;
  455. +     }
  456.       if(xfont == ulfont){
  457.           for(k=w/t.Char;k>0;k--)oput('_');
  458.           for(k=w/t.Char;k>0;k--)oput('\b');
  459. ***************
  460. *** 158,163
  461.               oput(' ');
  462.           }else{
  463.               if(plotmode)oputs(t.plotoff);
  464.               *obufp++ = *codep++;
  465.               if(obufp == (obuf + OBUFSZ + ascii - 1))flusho();
  466.   /*            oput(*codep++);*/
  467.  
  468. --- 156,162 -----
  469.               oput(' ');
  470.           }else{
  471.               if(plotmode)oputs(t.plotoff);
  472. +             if(obufp >= (obuf + OBUFSZ + ascii - 1 - (bdmode?3:1)))flusho();
  473.               *obufp++ = *codep++;
  474.               if(bdmode && !*t.bdon){
  475.                   *obufp++ = '\b';
  476. ***************
  477. *** 159,165
  478.           }else{
  479.               if(plotmode)oputs(t.plotoff);
  480.               *obufp++ = *codep++;
  481. !             if(obufp == (obuf + OBUFSZ + ascii - 1))flusho();
  482.   /*            oput(*codep++);*/
  483.           }
  484.       }
  485.  
  486. --- 158,167 -----
  487.               if(plotmode)oputs(t.plotoff);
  488.               if(obufp >= (obuf + OBUFSZ + ascii - 1 - (bdmode?3:1)))flusho();
  489.               *obufp++ = *codep++;
  490. !             if(bdmode && !*t.bdon){
  491. !                 *obufp++ = '\b';
  492. !                 *obufp++ = codep[-1];
  493. !             }
  494.   /*            oput(*codep++);*/
  495.           }
  496.       }
  497. SHAR_EOF
  498. fi
  499. if test -f 'option.c'
  500. then
  501.     echo shar: "will not over-write existing file 'option.c'"
  502. else
  503. cat << \SHAR_EOF > 'option.c'
  504. /*
  505.  * Process command line options.
  506.  * Each option is a single letter which controls a program variable.
  507.  * The options have defaults which may be changed via
  508.  * the command line option, or toggled via the "-" command.
  509.  */
  510.  
  511. #include "less.h"
  512.  
  513. #define    toupper(c)    ((c)-'a'+'A')
  514.  
  515. /*
  516.  * Types of options.
  517.  */
  518. #define    BOOL        01    /* Boolean option: 0 or 1 */
  519. #define    TRIPLE        02    /* Triple-valued option: 0, 1 or 2 */
  520. #define    NUMBER        04    /* Numeric option */
  521. #define    NO_TOGGLE    0100    /* Option cannot be toggled with "-" cmd */
  522.  
  523. /*
  524.  * Variables controlled by command line options.
  525.  */
  526. public int p_nbufs, f_nbufs;    /* Number of buffers.  There are two values,
  527.                    one used for input from a pipe and 
  528.                    the other for input from a file. */
  529. public int clean_data;        /* Can we assume the data is "clean"? 
  530.                    (That is, free of nulls, etc) */
  531. public int quiet;        /* Should we suppress the audible bell? */
  532. public int top_search;        /* Should forward searches start at the top 
  533.                    of the screen? (alternative is bottom) */
  534. public int top_scroll;        /* Repaint screen from top?
  535.                    (alternative is scroll from bottom) */
  536. public int pr_type;        /* Type of prompt (short, medium, long) */
  537. public int bs_mode;        /* How to process backspaces */
  538. public int know_dumb;        /* Don't complain about dumb terminals */
  539. public int quit_at_eof;        /* Quit after hitting end of file twice */
  540. public int squeeze;        /* Squeeze multiple blank lines into one */
  541. public int tabstop;        /* Tab settings */
  542. public int back_scroll;        /* Repaint screen on backwards movement */
  543. public int twiddle;        /* Display "~" for lines after EOF */
  544.  
  545. extern int nbufs;
  546. extern int sc_window;
  547. extern char *first_cmd;
  548. extern char *every_first_cmd;
  549.  
  550. #define    DEF_F_NBUFS    5    /* Default for f_nbufs */
  551. #define    DEF_P_NBUFS    12    /* Default for p_nbufs */
  552.  
  553. static struct option
  554. {
  555.     char oletter;        /* The controlling letter (a-z) */
  556.     char otype;        /* Type of the option */
  557.     int odefault;        /* Default value */
  558.     int *ovar;        /* Pointer to the associated variable */
  559.     char *odesc[3];        /* Description of each value */
  560. } option[] =
  561. {
  562.     { 'c', BOOL, 0, &clean_data,
  563.         { "Don't assume data is clean",
  564.           "Assume data is clean",
  565.           NULL
  566.         }
  567.     },
  568.     { 'd', BOOL|NO_TOGGLE, 0, &know_dumb,
  569.         { NULL, NULL, NULL}
  570.     },
  571.     { 'e', BOOL, 0, &quit_at_eof,
  572.         { "Don't quit at end-of-file",
  573.           "Quit at end-of-file",
  574.           NULL
  575.         }
  576.     },
  577.     { 'h', NUMBER, -1, &back_scroll,
  578.         { "Backwards scroll limit is %d lines",
  579.           NULL, NULL
  580.         }
  581.     },
  582.     { 'p', BOOL, 0, &top_scroll,
  583.         { "Repaint by scrolling from bottom of screen",
  584.           "Repaint by painting from top of screen",
  585.           NULL
  586.         }
  587.     },
  588.     { 'x', NUMBER, 8, &tabstop,
  589.         { "Tab stops every %d spaces", 
  590.           NULL, NULL 
  591.         }
  592.     },
  593.     { 's', BOOL, 0, &squeeze,
  594.         { "Don't squeeze multiple blank lines",
  595.           "Squeeze multiple blank lines",
  596.           NULL
  597.         }
  598.     },
  599.     { 't', BOOL, 1, &top_search,
  600.         { "Forward search starts from bottom of screen",
  601.           "Forward search starts from top of screen",
  602.           NULL
  603.         }
  604.     },
  605.     { 'w', BOOL, 1, &twiddle,
  606.         { "Display nothing for lines after end-of-file",
  607.           "Display ~ for lines after end-of-file",
  608.           NULL
  609.         }
  610.     },
  611.     { 'm', TRIPLE, 0, &pr_type,
  612.         { "Prompt with a colon",
  613.           "Prompt with a message",
  614.           "Prompt with a verbose message"
  615.         }
  616.     },
  617.     { 'q', TRIPLE, 0, &quiet,
  618.         { "Ring the bell for errors AND at eof/bof",
  619.           "Ring the bell for errors but not at eof/bof",
  620.           "Never ring the bell"
  621.         }
  622.     },
  623.     { 'u', TRIPLE, 0, &bs_mode,
  624.         { "Underlined text displayed in underline mode",
  625.           "All backspaces cause overstrike",
  626.           "Backspaces print as ^H"
  627.         }
  628.     },
  629.     { 'z', NUMBER, 24, &sc_window,
  630.         { "Scroll window size is %d lines",
  631.           NULL, NULL
  632.         }
  633.     },
  634.     { '\0' }
  635. };
  636.  
  637. public char all_options[64];    /* List of all valid options */
  638.  
  639. /*
  640.  * Initialize each option to its default value.
  641.  */
  642.     public void
  643. init_option()
  644. {
  645.     register struct option *o;
  646.     register char *p;
  647.  
  648.     /*
  649.      * First do special cases, not in option table.
  650.      */
  651.     first_cmd = every_first_cmd = NULL;
  652.     f_nbufs = DEF_F_NBUFS;        /* -bf */
  653.     p_nbufs = DEF_P_NBUFS;        /* -bp */
  654.  
  655.     p = all_options;
  656.     *p++ = 'b';
  657.  
  658.     for (o = option;  o->oletter != '\0';  o++)
  659.     {
  660.         /*
  661.          * Set each variable to its default.
  662.          * Also make a list of all options, in "all_options".
  663.          */
  664.         *(o->ovar) = o->odefault;
  665.         *p++ = o->oletter;
  666.         if (o->otype & TRIPLE)
  667.             *p++ = toupper(o->oletter);
  668.     }
  669.     *p = '\0';
  670. }
  671.  
  672. /*
  673.  * Toggle command line flags from within the program.
  674.  * Used by the "-" command.
  675.  */
  676.     public void
  677. toggle_option(c)
  678.     int c;
  679. {
  680.     register struct option *o;
  681.     char message[100];
  682.     char buf[5];
  683.  
  684.     /*
  685.      * First check for special cases not handled by the option table.
  686.      */
  687.     switch (c)
  688.     {
  689.     case 'b':
  690.         sprintf(message, "%d buffers", nbufs);
  691.         error(message);
  692.         return;
  693.     }
  694.  
  695.  
  696.     for (o = option;  o->oletter != '\0';  o++)
  697.     {
  698.         if ((o->otype & BOOL) && (o->oletter == c) &&
  699.             (o->otype & NO_TOGGLE) == 0)
  700.         {
  701.             /*
  702.              * Boolean option: 
  703.              * just toggle it.
  704.              */
  705.             *(o->ovar) = ! *(o->ovar);
  706.             error(o->odesc[*(o->ovar)]);
  707.             return;
  708.         } else if ((o->otype & TRIPLE) && (o->oletter == c) &&
  709.             (o->otype & NO_TOGGLE) == 0)
  710.         {
  711.             /*
  712.              * Triple-valued option with lower case letter:
  713.              * make it 1 unless already 1, then make it 0.
  714.              */
  715.             *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1;
  716.             error(o->odesc[*(o->ovar)]);
  717.             return;
  718.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c) &&
  719.             (o->otype & NO_TOGGLE) == 0)
  720.         {
  721.             /*
  722.              * Triple-valued option with upper case letter:
  723.              * make it 2 unless already 2, then make it 0.
  724.              */
  725.             *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2;
  726.             error(o->odesc[*(o->ovar)]);
  727.             return;
  728.         } else if ((o->otype & NUMBER) && (o->oletter == c) &&
  729.             (o->otype & NO_TOGGLE) == 0)
  730.         {
  731.             sprintf(message, o->odesc[0], *(o->ovar));
  732.             error(message);
  733.             return;
  734.         }
  735.     }
  736.  
  737.     if (control_char(c))
  738.         sprintf(buf, "^%c", carat_char(c));
  739.     else
  740.         sprintf(buf, "%c", c);
  741.     sprintf(message, "\"-%s\": no such flag.  Use one of \"%s\"", 
  742.         buf, all_options);
  743.     error(message);
  744. }
  745.  
  746. /*
  747.  * Scan an argument (either from command line or from LESS environment 
  748.  * variable) and process it.
  749.  */
  750.     public void
  751. scan_option(s)
  752.     char *s;
  753. {
  754.     register struct option *o;
  755.     register int c;
  756.  
  757.     if (s == NULL)
  758.         return;
  759.  
  760.     next:
  761.     if (*s == '\0')
  762.         return;
  763.     switch (c = *s++)
  764.     {
  765.     case '-':
  766.     case ' ':
  767.     case '\t':
  768.         goto next;
  769.     case '+':
  770.         if (*s == '+')
  771.             every_first_cmd = ++s;
  772.         first_cmd = s;
  773.         return;
  774.     case 'b':
  775.         switch (*s)
  776.         {
  777.         case 'f':
  778.             s++;
  779.             f_nbufs = getnum(&s, 'b');
  780.             break;
  781.         case 'p':
  782.             s++;
  783.             p_nbufs = getnum(&s, 'b');
  784.             break;
  785.         default:
  786.             f_nbufs = p_nbufs = getnum(&s, 'b');
  787.             break;
  788.         }
  789.         goto next;
  790.     case '0':  case '1':  case '2':  case '3':  case '4':
  791.     case '5':  case '6':  case '7':  case '8':  case '9':
  792.         {
  793.             /*
  794.              * Handle special "more" compatibility form "-number"
  795.              * to set the scrolling window size.
  796.              */
  797.             s--;
  798.             sc_window = getnum(&s, '-');
  799.             goto next;
  800.         }
  801.     }
  802.  
  803.     for (o = option;  o->oletter != '\0';  o++)
  804.     {
  805.         if ((o->otype & BOOL) && (o->oletter == c))
  806.         {
  807.             *(o->ovar) = ! o->odefault;
  808.             goto next;
  809.         } else if ((o->otype & TRIPLE) && (o->oletter == c))
  810.         {
  811.             *(o->ovar) = (o->odefault == 1) ? 0 : 1;
  812.             goto next;
  813.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
  814.         {
  815.             *(o->ovar) = (o->odefault == 2) ? 0 : 2;
  816.             goto next;
  817.         } else if ((o->otype & NUMBER) && (o->oletter == c))
  818.         {
  819.             *(o->ovar) = getnum(&s, c);
  820.             goto next;
  821.         }
  822.     }
  823.  
  824.     printf("\"-%c\": invalid flag\n", c);
  825.     exit(1);
  826. }
  827.  
  828. /*
  829.  * Translate a string into a number.
  830.  * Like atoi(), but takes a pointer to a char *, and updates
  831.  * the char * to point after the translated number.
  832.  */
  833.     static int
  834. getnum(sp, c)
  835.     char **sp;
  836.     int c;
  837. {
  838.     register char *s;
  839.     register int n;
  840.  
  841.     s = *sp;
  842.     if (*s < '0' || *s > '9')
  843.     {
  844.         printf("number is required after -%c\n", c);
  845.         exit(1);
  846.     }
  847.  
  848.     n = 0;
  849.     while (*s >= '0' && *s <= '9')
  850.         n = 10 * n + *s++ - '0';
  851.     *sp = s;
  852.     return (n);
  853. }
  854. SHAR_EOF
  855. fi
  856. if test -f 'output.c'
  857. then
  858.     echo shar: "will not over-write existing file 'output.c'"
  859. else
  860. cat << \SHAR_EOF > 'output.c'
  861. /*
  862.  * High level routines dealing with the output to the screen.
  863.  */
  864.  
  865. #include "less.h"
  866.  
  867. extern int sigs;
  868. extern int sc_width, sc_height;
  869. extern int bo_width, be_width;
  870. extern int ul_width, ue_width;
  871. extern int so_width, se_width;
  872. extern int tabstop;
  873. extern int twiddle;
  874. extern char *line;
  875. extern char *first_cmd;
  876.  
  877. /*
  878.  * Display the line which is in the line buffer.
  879.  */
  880.     public void
  881. put_line()
  882. {
  883.     register char *p;
  884.     register int c;
  885.     register int column;
  886.     extern int auto_wrap, ignaw;
  887.  
  888.     if (sigs)
  889.         /*
  890.          * Don't output if a signal is pending.
  891.          */
  892.         return;
  893.  
  894.     if (line == NULL)
  895.         line = (twiddle) ? "~" : "";
  896.  
  897.     column = 0;
  898.     for (p = line;  *p != '\0';  p++)
  899.     {
  900.         switch (c = *p)
  901.         {
  902.         case UL_CHAR:
  903.             ul_enter();
  904.             column += ul_width;
  905.             break;
  906.         case UE_CHAR:
  907.             ul_exit();
  908.             column += ue_width;
  909.             break;
  910.         case BO_CHAR:
  911.             bo_enter();
  912.             column += bo_width;
  913.             break;
  914.         case BE_CHAR:
  915.             bo_exit();
  916.             column += be_width;
  917.             break;
  918.         case '\t':
  919.             do
  920.             {
  921.                 putc(' ');
  922.                 column++;
  923.             } while ((column % tabstop) != 0);
  924.             break;
  925.         case '\b':
  926.             putbs();
  927.             column--;
  928.             break;
  929.         default:
  930.             if (c & 0200)
  931.             {
  932.                 putc('^');
  933.                 putc(c & 0177);
  934.                 column += 2;
  935.             } else
  936.             {
  937.                 putc(c);
  938.                 column++;
  939.             }
  940.         }
  941.     }
  942.     if (column < sc_width || !auto_wrap || ignaw)
  943.         putc('\n');
  944. }
  945.  
  946. /*
  947.  * Is a given character a "control" character?
  948.  * {{ ASCII DEPENDENT }}
  949.  */
  950.     public int
  951. control_char(c)
  952.     int c;
  953. {
  954.     return (c < ' ' || c == '\177');
  955. }
  956.  
  957. /*
  958.  * Return the printable character used to identify a control character
  959.  * (printed after a carat; e.g. '\3' => "^C").
  960.  * {{ ASCII DEPENDENT }}
  961.  */
  962.     public int
  963. carat_char(c)
  964.     int c;
  965. {
  966.     return ((c == '\177') ? '?' : (c | 0100));
  967. }
  968.  
  969.  
  970. static char obuf[1024];
  971. static char *ob = obuf;
  972.  
  973. /*
  974.  * Flush buffered output.
  975.  */
  976.     public void
  977. flush()
  978. {
  979.     write(1, obuf, ob-obuf);
  980.     ob = obuf;
  981. }
  982.  
  983. /*
  984.  * Discard buffered output.
  985.  */
  986.     public void
  987. dropout()
  988. {
  989.     ob = obuf;
  990. }
  991.  
  992. /*
  993.  * Output a character.
  994.  */
  995.     public void
  996. putc(c)
  997.     int c;
  998. {
  999.     if (ob >= &obuf[sizeof(obuf)])
  1000.         flush();
  1001.     *ob++ = c;
  1002. }
  1003.  
  1004. /*
  1005.  * Output a string.
  1006.  */
  1007.     public void
  1008. puts(s)
  1009.     register char *s;
  1010. {
  1011.     while (*s != '\0')
  1012.         putc(*s++);
  1013. }
  1014.  
  1015. /*
  1016.  * Output a message in the lower left corner of the screen
  1017.  * and wait for carriage return.
  1018.  */
  1019.  
  1020. static char return_to_continue[] = "  (press RETURN)";
  1021.  
  1022.     public void
  1023. error(s)
  1024.     char *s;
  1025. {
  1026.     register int c;
  1027.     static char buf[2];
  1028.  
  1029.     lower_left();
  1030.     clear_eol();
  1031.     so_enter();
  1032.     puts(s);
  1033.     puts(return_to_continue);
  1034.     so_exit();
  1035.  
  1036. #if ONLY_RETURN
  1037.     while ((c = getc()) != '\n' && c != '\r')
  1038.         bell();
  1039. #else
  1040.     c = getc();
  1041.     if (c != '\n' && c != '\r' && c != ' ')
  1042.     {
  1043.         buf[0] = c;
  1044.         first_cmd = buf;
  1045.     }
  1046. #endif
  1047.  
  1048.     if (strlen(s) > sc_width)
  1049.         repaint();
  1050. }
  1051.  
  1052.     public int
  1053. error_width()
  1054. {
  1055.     /*
  1056.      * Don't use the last position, because some terminals
  1057.      * will scroll if you write in the last char of the last line.
  1058.      */
  1059.     return (sc_width - 
  1060.         (sizeof(return_to_continue) + so_width + se_width + 1));
  1061. }
  1062. SHAR_EOF
  1063. fi
  1064. if test -f 'pager_patch.c'
  1065. then
  1066.     echo shar: "will not over-write existing file 'pager_patch.c'"
  1067. else
  1068. cat << \SHAR_EOF > 'pager_patch.c'
  1069. /*
  1070.  * Special interface that checks for the environment variable PAGER.  If
  1071.  * present, the program specified is executed, otherwise OLD_PAGER_NEW_LOCATION
  1072.  * (specified below).  This program should replace /usr/ucb/more (or whatever
  1073.  * your default pager is) and more should be moved to OLD_PAGER_NEW_LOCATION.
  1074.  * This is essentially a fix for all the programs which *should* check for the
  1075.  * environment variable PAGER, but don't - hopefully it will be obsoleted as
  1076.  * old programs are update to check for PAGER so we can loose the overhead of
  1077.  * reexecuting even this small program ...
  1078.  *
  1079.  * Casey Leedom (lll-crg.arpa!csustan!casey) - 5/29/86
  1080.  */
  1081.  
  1082. #ifndef OLD_PAGER_NEW_LOCATION
  1083. #    define    OLD_PAGER_NEW_LOCATION    "/usr/ucb/More"
  1084. #endif !OLD_PAGER_NEW_LOCATION
  1085.  
  1086. void
  1087. main(argc, argv)
  1088.     int    argc;
  1089.     char    **argv;
  1090. {
  1091.     char    *pager, *getenv();
  1092.  
  1093.     if (!(pager = getenv("PAGER")))
  1094.         pager = OLD_PAGER_NEW_LOCATION;
  1095.     (void) execv(pager, argv);
  1096. }
  1097. SHAR_EOF
  1098. fi
  1099. if test -f 'position.c'
  1100. then
  1101.     echo shar: "will not over-write existing file 'position.c'"
  1102. else
  1103. cat << \SHAR_EOF > 'position.c'
  1104. /*
  1105.  * Routines dealing with the "position" table.
  1106.  * This is a table which tells the position (in the input file) of the
  1107.  * first char on each currently displayed line.
  1108.  *
  1109.  * {{ The position table is scrolled by moving all the entries.
  1110.  *    Would be better to have a circular table 
  1111.  *    and just change a couple of pointers. }}
  1112.  */
  1113.  
  1114. #include "less.h"
  1115. #include "position.h"
  1116.  
  1117. #define    NPOS    100        /* {{ sc_height must be less than NPOS }} */
  1118. static POSITION table[NPOS];    /* The position table */
  1119.  
  1120. extern int sc_width, sc_height;
  1121.  
  1122. /*
  1123.  * Return the position of one of:
  1124.  *    the top (first) line on the screen
  1125.  *    the second line on the screen
  1126.  *    the bottom line on the screen
  1127.  *    the line after the bottom line on the screen
  1128.  */
  1129.     public POSITION
  1130. position(where)
  1131.     int where;
  1132. {
  1133.     switch (where)
  1134.     {
  1135.     case BOTTOM:
  1136.         where = sc_height - 2;
  1137.         break;
  1138.     case BOTTOM_PLUS_ONE:
  1139.         where = sc_height - 1;
  1140.         break;
  1141.     }
  1142.     return (table[where]);
  1143. }
  1144.  
  1145. /*
  1146.  * Add a new file position to the bottom of the position table.
  1147.  */
  1148.     public void
  1149. add_forw_pos(pos)
  1150.     POSITION pos;
  1151. {
  1152.     register int i;
  1153.  
  1154.     /*
  1155.      * Scroll the position table up.
  1156.      */
  1157.     for (i = 1;  i < sc_height;  i++)
  1158.         table[i-1] = table[i];
  1159.     table[sc_height - 1] = pos;
  1160. }
  1161.  
  1162. /*
  1163.  * Add a new file position to the top of the position table.
  1164.  */
  1165.     public void
  1166. add_back_pos(pos)
  1167.     POSITION pos;
  1168. {
  1169.     register int i;
  1170.  
  1171.     /*
  1172.      * Scroll the position table down.
  1173.      */
  1174.     for (i = sc_height - 1;  i > 0;  i--)
  1175.         table[i] = table[i-1];
  1176.     table[0] = pos;
  1177. }
  1178.  
  1179. /*
  1180.  * Initialize the position table, done whenever we clear the screen.
  1181.  */
  1182.     public void
  1183. pos_clear()
  1184. {
  1185.     register int i;
  1186.  
  1187.     for (i = 0;  i < sc_height;  i++)
  1188.         table[i] = NULL_POSITION;
  1189. }
  1190.  
  1191. /*
  1192.  * See if the byte at a specified position is currently on the screen.
  1193.  * Check the position table to see if the position falls within its range.
  1194.  * Return the position table entry if found, -1 if not.
  1195.  */
  1196.     public int
  1197. onscreen(pos)
  1198.     POSITION pos;
  1199. {
  1200.     register int i;
  1201.  
  1202.     if (pos < table[0])
  1203.         return (-1);
  1204.     for (i = 1;  i < sc_height;  i++)
  1205.         if (pos < table[i])
  1206.             return (i-1);
  1207.     return (-1);
  1208. }
  1209. SHAR_EOF
  1210. fi
  1211. if test -f 'position.h'
  1212. then
  1213.     echo shar: "will not over-write existing file 'position.h'"
  1214. else
  1215. cat << \SHAR_EOF > 'position.h'
  1216. /*
  1217.  * Include file for interfacing to position.c modules.
  1218.  */
  1219. #define    TOP        0
  1220. #define    TOP_PLUS_ONE    1
  1221. #define    BOTTOM        -1
  1222. #define    BOTTOM_PLUS_ONE    -2
  1223. SHAR_EOF
  1224. fi
  1225. if test -f 'prim.c'
  1226. then
  1227.     echo shar: "will not over-write existing file 'prim.c'"
  1228. else
  1229. cat << \SHAR_EOF > 'prim.c'
  1230. /*
  1231.  * Primitives for displaying the file on the screen.
  1232.  */
  1233.  
  1234. #include "less.h"
  1235. #include "position.h"
  1236.  
  1237. public int hit_eof;    /* Keeps track of how many times we hit end of file */
  1238.  
  1239. extern int quiet;
  1240. extern int top_search;
  1241. extern int top_scroll;
  1242. extern int back_scroll;
  1243. extern int sc_width, sc_height;
  1244. extern int sigs;
  1245. extern char *line;
  1246. extern char *first_cmd;
  1247.  
  1248. /*
  1249.  * Sound the bell to indicate he is trying to move past end of file.
  1250.  */
  1251.     static void
  1252. eof_bell()
  1253. {
  1254.     if (quiet == NOT_QUIET)
  1255.         bell();
  1256.     else
  1257.         vbell();
  1258. }
  1259.  
  1260. /*
  1261.  * Check to see if the end of file is currently "displayed".
  1262.  */
  1263.     static void
  1264. eof_check()
  1265. {
  1266.     POSITION pos;
  1267.  
  1268.     /*
  1269.      * If the bottom line is empty, we are at EOF.
  1270.      * If the bottom line ends at the file length,
  1271.      * we must be just at EOF.
  1272.      */
  1273.     pos = position(BOTTOM_PLUS_ONE);
  1274.     if (pos == NULL_POSITION || pos == ch_length())
  1275.         hit_eof++;
  1276. }
  1277.  
  1278. /*
  1279.  * Display n lines, scrolling forward, 
  1280.  * starting at position pos in the input file.
  1281.  * "force" means display the n lines even if we hit end of file.
  1282.  * "only_last" means display only the last screenful if n > screen size.
  1283.  */
  1284.     static void
  1285. forw(n, pos, force, only_last)
  1286.     register int n;
  1287.     POSITION pos;
  1288.     int force;
  1289.     int only_last;
  1290. {
  1291.     int eof = 0;
  1292.     int nlines = 0;
  1293.     int repaint_flag;
  1294.  
  1295.     /*
  1296.      * repaint_flag tells us not to display anything till the end, 
  1297.      * then just repaint the entire screen.
  1298.      */
  1299.     repaint_flag = (only_last && n > sc_height-1);
  1300.  
  1301.     if (!repaint_flag)
  1302.     {
  1303.         if (top_scroll && n >= sc_height - 1)
  1304.         {
  1305.             /*
  1306.              * Start a new screen.
  1307.              * {{ This is not really desirable if we happen
  1308.              *    to hit eof in the middle of this screen,
  1309.              *    but we don't know if that will happen now. }}
  1310.              */
  1311.             clear();
  1312.             home();
  1313.             force = 1;
  1314.         } else
  1315.         {
  1316.             lower_left();
  1317.             clear_eol();
  1318.         }
  1319.  
  1320.         if (pos != position(BOTTOM_PLUS_ONE))
  1321.         {
  1322.             /*
  1323.              * This is not contiguous with what is
  1324.              * currently displayed.  Clear the screen image 
  1325.              * (position table) and start a new screen.
  1326.              */
  1327.             pos_clear();
  1328.             add_forw_pos(pos);
  1329.             force = 1;
  1330.             if (top_scroll)
  1331.             {
  1332.                 clear();
  1333.                 home();
  1334.             } else
  1335.             {
  1336.                 puts("...skipping...\n");
  1337.             }
  1338.         }
  1339.     }
  1340.  
  1341.     while (--n >= 0)
  1342.     {
  1343.         /*
  1344.          * Read the next line of input.
  1345.          */
  1346.         pos = forw_line(pos);
  1347.         if (pos == NULL_POSITION)
  1348.         {
  1349.             /*
  1350.              * End of file: stop here unless the top line 
  1351.              * is still empty, or "force" is true.
  1352.              */
  1353.             eof = 1;
  1354.             if (!force && position(TOP) != NULL_POSITION)
  1355.                 break;
  1356.             line = NULL;
  1357.         }
  1358.         /*
  1359.          * Add the position of the next line to the position table.
  1360.          * Display the current line on the screen.
  1361.          */
  1362.         add_forw_pos(pos);
  1363.         nlines++;
  1364.         if (!repaint_flag)
  1365.             put_line();
  1366.     }
  1367.  
  1368.     if (eof)
  1369.         hit_eof++;
  1370.     else
  1371.         eof_check();
  1372.     if (nlines == 0)
  1373.         eof_bell();
  1374.     else if (repaint_flag)
  1375.         repaint();
  1376. }
  1377.  
  1378. /*
  1379.  * Display n lines, scrolling backward.
  1380.  */
  1381.     static void
  1382. back(n, pos, force, only_last)
  1383.     register int n;
  1384.     POSITION pos;
  1385.     int force;
  1386.     int only_last;
  1387. {
  1388.     int nlines = 0;
  1389.     int repaint_flag;
  1390.  
  1391.     repaint_flag = (n > back_scroll || (only_last && n > sc_height-1));
  1392.     hit_eof = 0;
  1393.     while (--n >= 0)
  1394.     {
  1395.         /*
  1396.          * Get the previous line of input.
  1397.          */
  1398.         pos = back_line(pos);
  1399.         if (pos == NULL_POSITION)
  1400.         {
  1401.             /*
  1402.              * Beginning of file: stop here unless "force" is true.
  1403.              */
  1404.             if (!force)
  1405.                 break;
  1406.             line = NULL;
  1407.         }
  1408.         /*
  1409.          * Add the position of the previous line to the position table.
  1410.          * Display the line on the screen.
  1411.          */
  1412.         add_back_pos(pos);
  1413.         nlines++;
  1414.         if (!repaint_flag)
  1415.         {
  1416.             home();
  1417.             add_line();
  1418.             put_line();
  1419.         }
  1420.     }
  1421.  
  1422.     eof_check();
  1423.     if (nlines == 0)
  1424.         eof_bell();
  1425.     else if (repaint_flag)
  1426.         repaint();
  1427. }
  1428.  
  1429. /*
  1430.  * Display n more lines, forward.
  1431.  * Start just after the line currently displayed at the bottom of the screen.
  1432.  */
  1433.     public void
  1434. forward(n, only_last)
  1435.     int n;
  1436.     int only_last;
  1437. {
  1438.     POSITION pos;
  1439.  
  1440.     pos = position(BOTTOM_PLUS_ONE);
  1441.     if (pos == NULL_POSITION)
  1442.     {
  1443.         eof_bell();
  1444.         hit_eof++;
  1445.         return;
  1446.     }
  1447.     forw(n, pos, 0, only_last);
  1448. }
  1449.  
  1450. /*
  1451.  * Display n more lines, backward.
  1452.  * Start just before the line currently displayed at the top of the screen.
  1453.  */
  1454.     public void
  1455. backward(n, only_last)
  1456.     int n;
  1457.     int only_last;
  1458. {
  1459.     POSITION pos;
  1460.  
  1461.     pos = position(TOP);
  1462.     if (pos == NULL_POSITION)
  1463.     {
  1464.         /* 
  1465.          * This will almost never happen,
  1466.          * because the top line is almost never empty. 
  1467.          */
  1468.         eof_bell();
  1469.         return;   
  1470.     }
  1471.     back(n, pos, 0, only_last);
  1472. }
  1473.  
  1474. /*
  1475.  * Repaint the screen, starting from a specified position.
  1476.  */
  1477.     static void
  1478. prepaint(pos)    
  1479.     POSITION pos;
  1480. {
  1481.     hit_eof = 0;
  1482.     forw(sc_height-1, pos, 0, 0);
  1483. }
  1484.  
  1485. /*
  1486.  * Repaint the screen.
  1487.  */
  1488.     public void
  1489. repaint()
  1490. {
  1491.     /*
  1492.      * Start at the line currently at the top of the screen
  1493.      * and redisplay the screen.
  1494.      */
  1495.     prepaint(position(TOP));
  1496. }
  1497.  
  1498. /*
  1499.  * Jump to the end of the file.
  1500.  * It is more convenient to paint the screen backward,
  1501.  * from the end of the file toward the beginning.
  1502.  */
  1503.     public void
  1504. jump_forw()
  1505. {
  1506.     POSITION pos;
  1507.  
  1508.     if (ch_end_seek())
  1509.     {
  1510.         error("Cannot seek to end of file");
  1511.         return;
  1512.     }
  1513.     pos = ch_tell();
  1514.     clear();
  1515.     pos_clear();
  1516.     add_back_pos(pos);
  1517.     back(sc_height - 1, pos, 0, 0);
  1518. }
  1519.  
  1520. /*
  1521.  * Jump to line n in the file.
  1522.  */
  1523.     public void
  1524. jump_back(n)
  1525.     register int n;
  1526. {
  1527.     register int c;
  1528.  
  1529.     /*
  1530.      * This is done the slow way, by starting at the beginning
  1531.      * of the file and counting newlines.
  1532.      */
  1533.     if (ch_seek((POSITION)0))
  1534.     {
  1535.         /* 
  1536.          * Probably a pipe with beginning of file no longer buffered. 
  1537.          */
  1538.         error("Cannot get to beginning of file");
  1539.         return;
  1540.     }
  1541.  
  1542.     /*
  1543.      * Start counting lines.
  1544.      */
  1545.     while (--n > 0)
  1546.     {
  1547.         while ((c = ch_forw_get()) != '\n')
  1548.             if (c == EOF)
  1549.             {
  1550.                 error("File is not that long");
  1551.                 /* {{ Maybe tell him how long it is? }} */
  1552.                 return;
  1553.             }
  1554.     }
  1555.  
  1556.     /*
  1557.      * Finally found the place to start.
  1558.      * Clear and redisplay the screen from there.
  1559.      *
  1560.      * {{ We *could* figure out if the new position is 
  1561.      *    close enough to just scroll there without clearing
  1562.      *    the screen, but it's not worth it. }}
  1563.      */
  1564.     prepaint(ch_tell());
  1565. }
  1566.  
  1567. /*
  1568.  * Jump to a specified percentage into the file.
  1569.  * This is a poor compensation for not being able to
  1570.  * quickly jump to a specific line number.
  1571.  */
  1572.     public void
  1573. jump_percent(percent)
  1574.     int percent;
  1575. {
  1576.     POSITION pos, len;
  1577.  
  1578.     /*
  1579.      * Determine the position in the file
  1580.      * (the specified percentage of the file's length).
  1581.      */
  1582.     if ((len = ch_length()) == NULL_POSITION)
  1583.     {
  1584.         error("Don't know length of file");
  1585.         return;
  1586.     }
  1587.     pos = (percent * len) / 100;
  1588.     jump_loc(pos);
  1589. }
  1590.  
  1591.     public void
  1592. jump_loc(pos)
  1593.     POSITION pos;
  1594. {
  1595.     register int c;
  1596.     register int nline;
  1597.     POSITION tpos;
  1598.  
  1599.     /*
  1600.      * See if the desired line is BEFORE the currently
  1601.      * displayed screen.  If so, see if it is close enough 
  1602.      * to scroll backwards to it.
  1603.      */
  1604.     tpos = position(TOP);
  1605.     if (pos < tpos)
  1606.     {
  1607.         for (nline = 1;  nline <= back_scroll;  nline++)
  1608.         {
  1609.             tpos = back_line(tpos);
  1610.             if (tpos == NULL_POSITION || tpos <= pos)
  1611.             {
  1612.                 back(nline, position(TOP), 1, 0);
  1613.                 return;
  1614.             }
  1615.         }
  1616.     } else if ((nline = onscreen(pos)) >= 0)
  1617.     {
  1618.         /*
  1619.          * The line is currently displayed.  
  1620.          * Just scroll there.
  1621.          */
  1622.         forw(nline, position(BOTTOM_PLUS_ONE), 1, 0);
  1623.         return;
  1624.     }
  1625.  
  1626.     /*
  1627.      * Line is not on screen.
  1628.      * Back up to the beginning of the current line.
  1629.      */
  1630.     if (ch_seek(pos))
  1631.     {
  1632.         error("Cannot seek to that position");
  1633.         return;
  1634.     }
  1635.     while ((c = ch_back_get()) != '\n' && c != EOF)
  1636.         ;
  1637.     if (c == '\n')
  1638.         (void) ch_forw_get();
  1639.  
  1640.     /*
  1641.      * Clear and paint the screen.
  1642.      */
  1643.     prepaint(ch_tell());
  1644. }
  1645.  
  1646. /*
  1647.  * The table of marks.
  1648.  * A mark is simply a position in the file.
  1649.  */
  1650. static POSITION marks[26];
  1651.  
  1652. /*
  1653.  * Initialize the mark table to show no marks are set.
  1654.  */
  1655.     public void
  1656. init_mark()
  1657. {
  1658.     int i;
  1659.  
  1660.     for (i = 0;  i < 26;  i++)
  1661.         marks[i] = NULL_POSITION;
  1662. }
  1663.  
  1664. /*
  1665.  * See if a mark letter is valid (between a and z).
  1666.  */
  1667.     static int
  1668. badmark(c)
  1669.     int c;
  1670. {
  1671.     if (c < 'a' || c > 'z')
  1672.     {
  1673.         error("Choose a letter between 'a' and 'z'");
  1674.         return (1);
  1675.     }
  1676.     return (0);
  1677. }
  1678.  
  1679. /*
  1680.  * Set a mark.
  1681.  */
  1682.     public void
  1683. setmark(c)
  1684.     int c;
  1685. {
  1686.     if (badmark(c))
  1687.         return;
  1688.     marks[c-'a'] = position(TOP);
  1689. }
  1690.  
  1691. /*
  1692.  * Go to a previously set mark.
  1693.  */
  1694.     public void
  1695. gomark(c)
  1696.     int c;
  1697. {
  1698.     POSITION pos;
  1699.  
  1700.     if (badmark(c))
  1701.         return;
  1702.     if ((pos = marks[c-'a']) == NULL_POSITION)
  1703.         error("mark not set");
  1704.     else
  1705.         jump_loc(pos);
  1706. }
  1707.  
  1708. /*
  1709.  * Search for the n-th occurence of a specified pattern, 
  1710.  * either forward (direction == '/'), or backwards (direction == '?').
  1711.  */
  1712.     public void
  1713. search(direction, pattern, n)
  1714.     int direction;
  1715.     char *pattern;
  1716.     register int n;
  1717. {
  1718.     register int search_forward = (direction == '/');
  1719.     POSITION pos, linepos;
  1720.  
  1721. #if RECOMP
  1722.     char *re_comp();
  1723.     char *errmsg;
  1724.  
  1725.     /*
  1726.      * (re_comp handles a null pattern internally, 
  1727.      *  so there is no need to check for a null pattern here.)
  1728.      */
  1729.     if ((errmsg = re_comp(pattern)) != NULL)
  1730.     {
  1731.         error(errmsg);
  1732.         return;
  1733.     }
  1734. #else
  1735. #if REGCMP
  1736.     char *regcmp();
  1737.     static char *cpattern = NULL;
  1738.  
  1739.     if (pattern == NULL || *pattern == '\0')
  1740.     {
  1741.         /*
  1742.          * A null pattern means use the previous pattern.
  1743.          * The compiled previous pattern is in cpattern, so just use it.
  1744.          */
  1745.         if (cpattern == NULL)
  1746.         {
  1747.             error("No previous regular expression");
  1748.             return;
  1749.         }
  1750.     } else
  1751.     {
  1752.         /*
  1753.          * Otherwise compile the given pattern.
  1754.          */
  1755.         char *s;
  1756.         if ((s = regcmp(pattern, 0)) == NULL)
  1757.         {
  1758.             error("Invalid pattern");
  1759.             return;
  1760.         }
  1761.         if (cpattern != NULL)
  1762.             free(cpattern);
  1763.         cpattern = s;
  1764.     }
  1765. #else
  1766.     static char lpbuf[100];
  1767.     static char *last_pattern = NULL;
  1768.  
  1769.     if (pattern == NULL || *pattern == '\0')
  1770.     {
  1771.         /*
  1772.          * Null pattern means use the previous pattern.
  1773.          */
  1774.         if (last_pattern == NULL)
  1775.         {
  1776.             error("No previous regular expression");
  1777.             return;
  1778.         }
  1779.         pattern = last_pattern;
  1780.     } else
  1781.     {
  1782.         strcpy(lpbuf, pattern);
  1783.         last_pattern = lpbuf;
  1784.     }
  1785. #endif
  1786. #endif
  1787.  
  1788.     /*
  1789.      * Figure out where to start the search.
  1790.      */
  1791.  
  1792.     if (position(TOP) == NULL_POSITION)
  1793.     {
  1794.         /*
  1795.          * Nothing is currently displayed.
  1796.          * Start at the beginning of the file.
  1797.          * (This case is mainly for first_cmd searches,
  1798.          * for example, "+/xyz" on the command line.)
  1799.          */
  1800.         pos = (POSITION)0;
  1801.     } else if (!search_forward)
  1802.     {
  1803.         /*
  1804.          * Backward search: start just before the top line
  1805.          * displayed on the screen.
  1806.          */
  1807.         pos = position(TOP);
  1808.     } else if (top_search)
  1809.     {
  1810.         /*
  1811.          * Forward search and "start from top".
  1812.          * Start at the second line displayed on the screen.
  1813.          */
  1814.         pos = position(TOP_PLUS_ONE);
  1815.     } else
  1816.     {
  1817.         /*
  1818.          * Forward search but don't "start from top".
  1819.          * Start just after the bottom line displayed on the screen.
  1820.          */
  1821.         pos = position(BOTTOM_PLUS_ONE);
  1822.     }
  1823.  
  1824.     if (pos == NULL_POSITION)
  1825.     {
  1826.         /*
  1827.          * Can't find anyplace to start searching from.
  1828.          */
  1829.         error("Nothing to search");
  1830.         return;
  1831.     }
  1832.  
  1833.     for (;;)
  1834.     {
  1835.         /*
  1836.          * Get lines until we find a matching one or 
  1837.          * until we hit end-of-file (or beginning-of-file 
  1838.          * if we're going backwards).
  1839.          */
  1840.         if (sigs)
  1841.             /*
  1842.              * A signal aborts the search.
  1843.              */
  1844.             return;
  1845.  
  1846.         if (search_forward)
  1847.         {
  1848.             /*
  1849.              * Read the next line, and save the 
  1850.              * starting position of that line in linepos.
  1851.              */
  1852.             linepos = pos;
  1853.             pos = forw_raw_line(pos);
  1854.         } else
  1855.         {
  1856.             /*
  1857.              * Read the previous line and save the
  1858.              * starting position of that line in linepos.
  1859.              */
  1860.             pos = back_raw_line(pos);
  1861.             linepos = pos;
  1862.         }
  1863.  
  1864.         if (pos == NULL_POSITION)
  1865.         {
  1866.             /*
  1867.              * We hit EOF/BOF without a match.
  1868.              */
  1869.             error("Pattern not found");
  1870.             return;
  1871.         }
  1872.  
  1873.         /*
  1874.          * Test the next line to see if we have a match.
  1875.          * This is done in a variety of ways, depending
  1876.          * on what pattern matching functions are available.
  1877.          */
  1878. #if REGCMP
  1879.         if ( (regex(cpattern, line) != NULL)
  1880. #else
  1881. #if RECOMP
  1882.         if ( (re_exec(line) == 1)
  1883. #else
  1884.         if ( (match(pattern, line))
  1885. #endif
  1886. #endif
  1887.                 && (--n <= 0) )
  1888.             /*
  1889.              * Found the matching line.
  1890.              */
  1891.             break;
  1892.     }
  1893.     jump_loc(linepos);
  1894. }
  1895.  
  1896. #if (!REGCMP) && (!RECOMP)
  1897. /*
  1898.  * We have neither regcmp() nor re_comp().
  1899.  * We use this function to do simple pattern matching.
  1900.  * It supports no metacharacters like *, etc.
  1901.  */
  1902.     static int
  1903. match(pattern, buf)
  1904.     char *pattern, *buf;
  1905. {
  1906.     register char *pp, *lp;
  1907.  
  1908.     for ( ;  *buf != '\0';  buf++)
  1909.     {
  1910.         for (pp = pattern, lp = buf;  *pp == *lp;  pp++, lp++)
  1911.             if (*pp == '\0' || *lp == '\0')
  1912.                 break;
  1913.         if (*pp == '\0')
  1914.             return (1);
  1915.     }
  1916.     return (0);
  1917. }
  1918. #endif
  1919. SHAR_EOF
  1920. fi
  1921. if test -f 'prompt.c'
  1922. then
  1923.     echo shar: "will not over-write existing file 'prompt.c'"
  1924. else
  1925. cat << \SHAR_EOF > 'prompt.c'
  1926. /*
  1927.  * Prompting and other messages.
  1928.  * There are three flavors of prompts, SHORT, MEDIUM and LONG,
  1929.  * selected by the -m/-M options.
  1930.  * A prompt is either a colon or a message composed of various
  1931.  * pieces, such as the name of the file being viewed, the percentage
  1932.  * into the file, etc.
  1933.  */
  1934.  
  1935. #include "less.h"
  1936. #include "position.h"
  1937.  
  1938. extern int pr_type;
  1939. extern int ispipe;
  1940. extern int hit_eof;
  1941. extern int new_file;
  1942. extern int sc_width;
  1943. extern char current_file[];
  1944. extern int ac;
  1945. extern char **av;
  1946. extern int curr_ac;
  1947.  
  1948. static char message[500];
  1949.  
  1950. /*
  1951.  * Append the name of the current file (to the message buffer).
  1952.  */
  1953.     static void
  1954. ap_filename()
  1955. {
  1956.     if (!ispipe)
  1957.         sprintf(message + strlen(message), 
  1958.             "%s", current_file);
  1959. }
  1960.  
  1961. /*
  1962.  * Append the "file N of M" message.
  1963.  */
  1964.     static void
  1965. ap_of()
  1966. {
  1967.     if (ac > 1)
  1968.         sprintf(message + strlen(message), 
  1969.             " (file %d of %d)", curr_ac+1, ac);
  1970. }
  1971.  
  1972. /*
  1973.  * Append the byte offset into the current file.
  1974.  */
  1975.     static void
  1976. ap_byte()
  1977. {
  1978.     POSITION pos, len;
  1979.  
  1980.     pos = position(BOTTOM_PLUS_ONE);
  1981.     if (pos != NULL_POSITION)
  1982.     {
  1983.         sprintf(message + strlen(message), 
  1984.             " byte %ld", pos);
  1985.         len = ch_length();
  1986.         if (len > 0)
  1987.             sprintf(message + strlen(message), 
  1988.                 "/%ld", len);
  1989.     }
  1990. }
  1991.  
  1992. /*
  1993.  * Append the percentage into the current file.
  1994.  * If we cannot find the percentage and must_print is true,
  1995.  * the use the byte offset.
  1996.  */
  1997.     static void
  1998. ap_percent(must_print)
  1999. {
  2000.     POSITION pos,len;
  2001.  
  2002.     pos = position(BOTTOM_PLUS_ONE);
  2003.     len = ch_length();
  2004.     if (len > 0 && pos != NULL_POSITION)
  2005.         sprintf(message + strlen(message),
  2006.             " (%ld%%)", (100 * pos) / len);
  2007.     else if (must_print)
  2008.         ap_byte();
  2009. }
  2010.  
  2011. /*
  2012.  * Append the end-of-file message.
  2013.  */
  2014.     static void
  2015. ap_eof()
  2016. {
  2017.     strcat(message, " END");
  2018.     if (curr_ac + 1 < ac)
  2019.         sprintf(message + strlen(message),
  2020.             " - Next: %s", av[curr_ac+1]);
  2021. }
  2022.  
  2023. /*
  2024.  * Return a message suitable for printing by the "=" command.
  2025.  */
  2026.     public char *
  2027. eq_message()
  2028. {
  2029.     message[0] = '\0';
  2030.     ap_filename();
  2031.     ap_of();
  2032.     ap_byte();
  2033.     ap_percent(0);
  2034.     /*
  2035.      * Truncate to the screen width.
  2036.      * {{ This isn't very nice. }}
  2037.      */
  2038.     message[error_width()] = '\0';
  2039.     return (message);
  2040. }
  2041.  
  2042. /*
  2043.  * Return a prompt.
  2044.  * This depends on the prompt type (SHORT, MEDIUM, LONG), etc.
  2045.  * If we can't come up with an appropriate prompt, return NULL
  2046.  * and the caller will prompt with a colon.
  2047.  */
  2048.     public char *
  2049. pr_string()
  2050. {
  2051.     message[0] = '\0';
  2052.     switch (pr_type)
  2053.     {
  2054.     case PR_SHORT:
  2055.         if (new_file)
  2056.         {
  2057.             ap_filename();
  2058.             ap_of();
  2059.         }
  2060.         if (hit_eof)
  2061.             ap_eof();
  2062.         break;
  2063.     case PR_MEDIUM:
  2064.         if (new_file)
  2065.         {
  2066.             ap_filename();
  2067.             ap_of();
  2068.         }
  2069.         if (hit_eof)
  2070.             ap_eof();
  2071.         else
  2072.             ap_percent(1);
  2073.         break;
  2074.     case PR_LONG:
  2075.         ap_filename();
  2076.         if (new_file)
  2077.             ap_of();
  2078.         ap_byte();
  2079.         if (hit_eof)
  2080.             ap_eof();
  2081.         else
  2082.             ap_percent(0);
  2083.         break;
  2084.     }
  2085.     new_file = 0;
  2086.     if (message[0] == '\0')
  2087.         return (NULL);
  2088.     /*
  2089.      * Truncate to the screen width.
  2090.      * {{ This isn't very nice. }}
  2091.      */
  2092.     message[sc_width-2] = '\0';
  2093.     return (message);
  2094. }
  2095. SHAR_EOF
  2096. fi
  2097. if test -f 'screen.c'
  2098. then
  2099.     echo shar: "will not over-write existing file 'screen.c'"
  2100. else
  2101. cat << \SHAR_EOF > 'screen.c'
  2102. /*
  2103.  * Routines which deal with the characteristics of the terminal.
  2104.  * Uses termcap to be as terminal-independent as possible.
  2105.  *
  2106.  * {{ Someday this should be rewritten to use curses. }}
  2107.  */
  2108.  
  2109. #include "less.h"
  2110. #if XENIX
  2111. #include <sys/types.h>
  2112. #include <sys/ioctl.h>
  2113. #endif
  2114.  
  2115. #if TERMIO
  2116. #include <termio.h>
  2117. #else
  2118. #include <sgtty.h>
  2119. #endif
  2120.  
  2121. /*
  2122.  * Strings passed to tputs() to do various terminal functions.
  2123.  */
  2124. static char
  2125.     *sc_pad,        /* Pad string */
  2126.     *sc_home,        /* Cursor home */
  2127.     *sc_addline,        /* Add line, scroll down following lines */
  2128.     *sc_lower_left,        /* Cursor to last line, first column */
  2129.     *sc_move,        /* General cursor positioning */
  2130.     *sc_clear,        /* Clear screen */
  2131.     *sc_eol_clear,        /* Clear to end of line */
  2132.     *sc_s_in,        /* Enter standout (highlighted) mode */
  2133.     *sc_s_out,        /* Exit standout mode */
  2134.     *sc_u_in,        /* Enter underline mode */
  2135.     *sc_u_out,        /* Exit underline mode */
  2136.     *sc_b_in,        /* Enter bold mode */
  2137.     *sc_b_out,        /* Exit bold mode */
  2138.     *sc_visual_bell,    /* Visual bell (flash screen) sequence */
  2139.     *sc_backspace,        /* Backspace cursor */
  2140.     *sc_init,        /* Startup terminal initialization */
  2141.     *sc_deinit;        /* Exit terminal de-intialization */
  2142. static int dumb;
  2143. static int hard;
  2144.  
  2145. public int auto_wrap;        /* Terminal does \r\n when write past margin */
  2146. public int ignaw;        /* Terminal ignores \n immediately after wrap */
  2147. public int erase_char, kill_char; /* The user's erase and line-kill chars */
  2148. public int sc_width, sc_height;    /* Height & width of screen */
  2149. public int sc_window = -1;    /* window size for forward and backward */
  2150. public int bo_width, be_width;    /* Printing width of boldface sequences */
  2151. public int ul_width, ue_width;    /* Printing width of underline sequences */
  2152. public int so_width, se_width;    /* Printing width of standout sequences */
  2153.  
  2154. /*
  2155.  * These two variables are sometimes defined in,
  2156.  * and needed by, the termcap library.
  2157.  * It may be necessary on some systems to declare them extern here.
  2158.  */
  2159. /*extern*/ short ospeed;    /* Terminal output baud rate */
  2160. /*extern*/ char PC;        /* Pad character */
  2161.  
  2162. extern int quiet;        /* If VERY_QUIET, use visual bell for bell */
  2163. extern int know_dumb;        /* Don't complain about a dumb terminal */
  2164. extern int back_scroll;
  2165. char *tgetstr();
  2166. char *tgoto();
  2167.  
  2168. /*
  2169.  * Change terminal to "raw mode", or restore to "normal" mode.
  2170.  * "Raw mode" means 
  2171.  *    1. An outstanding read will complete on receipt of a single keystroke.
  2172.  *    2. Input is not echoed.  
  2173.  *    3. On output, \n is mapped to \r\n.
  2174.  *    4. \t is NOT be expanded into spaces.
  2175.  *    5. Signal-causing characters such as ctrl-C (interrupt),
  2176.  *       etc. are NOT disabled.
  2177.  * It doesn't matter whether an input \n is mapped to \r, or vice versa.
  2178.  */
  2179.     public void
  2180. raw_mode(on)
  2181.     int on;
  2182. {
  2183. #if TERMIO
  2184.     struct termio s;
  2185.     static struct termio save_term;
  2186.  
  2187.     if (on)
  2188.     {
  2189.         /*
  2190.          * Get terminal modes.
  2191.          */
  2192.         ioctl(2, TCGETA, &s);
  2193.  
  2194.         /*
  2195.          * Save modes and set certain variables dependent on modes.
  2196.          */
  2197.         save_term = s;
  2198.         ospeed = s.c_cflag & CBAUD;
  2199.         erase_char = s.c_cc[VERASE];
  2200.         kill_char = s.c_cc[VKILL];
  2201.  
  2202.         /*
  2203.          * Set the modes to the way we want them.
  2204.          */
  2205.         s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  2206.         s.c_oflag |=  (OPOST|ONLCR|TAB3);
  2207.         s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
  2208.         s.c_cc[VMIN] = 1;
  2209.         s.c_cc[VTIME] = 0;
  2210.     } else
  2211.     {
  2212.         /*
  2213.          * Restore saved modes.
  2214.          */
  2215.         s = save_term;
  2216.     }
  2217.     ioctl(2, TCSETAW, &s);
  2218. #else
  2219.     struct sgttyb s;
  2220.     static struct sgttyb save_term;
  2221.  
  2222.     if (on)
  2223.     {
  2224.         /*
  2225.          * Get terminal modes.
  2226.          */
  2227.         ioctl(2, TIOCGETP, &s);
  2228.  
  2229.         /*
  2230.          * Save modes and set certain variables dependent on modes.
  2231.          */
  2232.         save_term = s;
  2233.         ospeed = s.sg_ospeed;
  2234.         erase_char = s.sg_erase;
  2235.         kill_char = s.sg_kill;
  2236.  
  2237.         /*
  2238.          * Set the modes to the way we want them.
  2239.          */
  2240.         s.sg_flags |= CBREAK;
  2241.         s.sg_flags &= ~(ECHO|XTABS);
  2242.     } else
  2243.     {
  2244.         /*
  2245.          * Restore saved modes.
  2246.          */
  2247.         s = save_term;
  2248.     }
  2249.     ioctl(2, TIOCSETN, &s);
  2250. #endif
  2251. }
  2252.  
  2253. static int couldnt = 0;
  2254.  
  2255.     static void
  2256. cannot(s)
  2257.     char *s;
  2258. {
  2259.     if (know_dumb)
  2260.         /* 
  2261.          * He knows he has a dumb terminal, so don't tell him. 
  2262.          */
  2263.         return;
  2264.  
  2265.     printf("WARNING: terminal cannot \"%s\"\n", s);
  2266.     couldnt = 1;
  2267. }
  2268.  
  2269. /*
  2270.  * Get terminal capabilities via termcap.
  2271.  */
  2272.     public void
  2273. get_term()
  2274. {
  2275.     char termbuf[1024];
  2276.     char *sp;
  2277.     static char sbuf[150];
  2278.  
  2279.     char *getenv();
  2280.  
  2281.     /*
  2282.      * Find out what kind of terminal this is.
  2283.      */
  2284.     if (tgetent(termbuf, getenv("TERM")) <= 0)
  2285.         dumb = 1;
  2286.  
  2287.     /*
  2288.      * Get size of the screen.
  2289.      */
  2290.     if (dumb || (sc_height = tgetnum("li")) < 0 || tgetflag("hc"))
  2291.     {
  2292.         /* Oh no, this is a hardcopy terminal. */
  2293.         hard = 1;
  2294.         sc_height = 24;
  2295.     }
  2296.     /*
  2297.      * This is terrible - the following if "knows" that it is being
  2298.      * executed *after* command line and environment options have
  2299.      * already been parsed.  Should it be executed in the main program
  2300.      * instead?
  2301.      */
  2302.     if ((sc_window <= 0) || (sc_window >= sc_height))
  2303.         sc_window = sc_height-1;
  2304.     if (dumb || (sc_width = tgetnum("co")) < 0)
  2305.         sc_width = 80;
  2306.  
  2307.     auto_wrap = tgetflag("am");
  2308.     ignaw = tgetflag("xn");
  2309.  
  2310.     /*
  2311.      * Assumes termcap variable "sg" is the printing width of
  2312.      * the standout sequence, the end standout sequence,
  2313.      * the underline sequence, the end underline sequence,
  2314.      * the boldface sequence, and the end boldface sequence.
  2315.      */
  2316.     if ((so_width = tgetnum("sg")) < 0)
  2317.         so_width = 0;
  2318.     be_width = bo_width = ue_width = ul_width = se_width = so_width;
  2319.  
  2320.     /*
  2321.      * Get various string-valued capabilities.
  2322.      */
  2323.     sp = sbuf;
  2324.  
  2325.     sc_pad = (dumb) ? NULL : tgetstr("pc", &sp);
  2326.     if (sc_pad != NULL)
  2327.         PC = *sc_pad;
  2328.  
  2329.     sc_init = (dumb) ? NULL : tgetstr("ti", &sp);
  2330.     if (sc_init == NULL)
  2331.         sc_init = "";
  2332.  
  2333.     sc_deinit= (dumb) ? NULL : tgetstr("te", &sp);
  2334.     if (sc_deinit == NULL)
  2335.         sc_deinit = "";
  2336.  
  2337.     sc_eol_clear = (dumb) ? NULL : tgetstr("ce", &sp);
  2338.     if (hard || sc_eol_clear == NULL || *sc_eol_clear == '\0')
  2339.     {
  2340.         cannot("clear to end of line");
  2341.         sc_eol_clear = "";
  2342.     }
  2343.  
  2344.     sc_clear = (dumb) ? NULL : tgetstr("cl", &sp);
  2345.     if (hard || sc_clear == NULL || *sc_clear == '\0')
  2346.     {
  2347.         cannot("clear screen");
  2348.         sc_clear = "\n\n";
  2349.     }
  2350.  
  2351.     sc_move = (dumb) ? NULL : tgetstr("cm", &sp);
  2352.     if (hard || sc_move == NULL || *sc_move == '\0')
  2353.     {
  2354.         /*
  2355.          * This is not an error here, because we don't 
  2356.          * always need sc_move.
  2357.          * We need it only if we don't have home or lower-left.
  2358.          */
  2359.         sc_move = "";
  2360.     }
  2361.  
  2362.     sc_s_in = (dumb) ? NULL : tgetstr("so", &sp);
  2363.     if (hard || sc_s_in == NULL)
  2364.         sc_s_in = "";
  2365.  
  2366.     sc_s_out = (dumb) ? NULL : tgetstr("se", &sp);
  2367.     if (hard || sc_s_out == NULL)
  2368.         sc_s_out = "";
  2369.  
  2370.     sc_u_in = (dumb) ? NULL : tgetstr("us", &sp);
  2371.     if (hard || sc_u_in == NULL)
  2372.         sc_u_in = sc_s_in;
  2373.  
  2374.     sc_u_out = (dumb) ? NULL : tgetstr("ue", &sp);
  2375.     if (hard || sc_u_out == NULL)
  2376.         sc_u_out = sc_s_out;
  2377.  
  2378.     sc_b_in = (dumb) ? NULL : tgetstr("md", &sp);
  2379.     if (hard || sc_b_in == NULL)
  2380.     {
  2381.         sc_b_in = sc_s_in;
  2382.         sc_b_out = sc_s_out;
  2383.     } else
  2384.     {
  2385.         sc_b_out = (dumb) ? NULL : tgetstr("me", &sp);
  2386.         if (hard || sc_b_out == NULL)
  2387.             sc_b_out = "";
  2388.     }
  2389.  
  2390.     sc_visual_bell = (dumb) ? NULL : tgetstr("vb", &sp);
  2391.     if (hard || sc_visual_bell == NULL)
  2392.         sc_visual_bell = "";
  2393.  
  2394.     sc_home = (dumb) ? NULL : tgetstr("ho", &sp);
  2395.     if (hard || sc_home == NULL || *sc_home == '\0')
  2396.     {
  2397.         if (*sc_move == '\0')
  2398.         {
  2399.             cannot("home cursor");
  2400.             /*
  2401.              * This last resort for sc_home is supposed to
  2402.              * be an up-arrow suggesting moving to the 
  2403.              * top of the "virtual screen". (The one in
  2404.              * your imagination as you try to use this on
  2405.              * a hard copy terminal.)
  2406.              */
  2407.             sc_home = "|\b^";        
  2408.         } else
  2409.         {
  2410.             /* 
  2411.              * No "home" string,
  2412.              * but we can use "move(0,0)".
  2413.              */
  2414.             strcpy(sp, tgoto(sc_move, 0, 0));
  2415.             sc_home = sp;
  2416.             sp += strlen(sp) + 1;
  2417.         }
  2418.     }
  2419.  
  2420.     sc_lower_left = (dumb) ? NULL : tgetstr("ll", &sp);
  2421.     if (hard || sc_lower_left == NULL || *sc_lower_left == '\0')
  2422.     {
  2423.         if (*sc_move == '\0')
  2424.         {
  2425.             cannot("move cursor to lower left of screen");
  2426.             sc_lower_left = "\r";
  2427.         } else
  2428.         {
  2429.             /*
  2430.              * No "lower-left" string, 
  2431.              * but we can use "move(0,last-line)".
  2432.              */
  2433.             strcpy(sp, tgoto(sc_move, 0, sc_height-1));
  2434.             sc_lower_left = sp;
  2435.             sp += strlen(sp) + 1;
  2436.         }
  2437.     }
  2438.  
  2439.     /*
  2440.      * To add a line at top of screen and scroll the display down,
  2441.      * we use "al" (add line) or "sr" (scroll reverse).
  2442.      */
  2443.     if (dumb)
  2444.         sc_addline = NULL;
  2445.     else if ((sc_addline = tgetstr("al", &sp)) == NULL || 
  2446.          *sc_addline == '\0')
  2447.         sc_addline = tgetstr("sr", &sp);
  2448.  
  2449.     if (hard || sc_addline == NULL || *sc_addline == '\0')
  2450.     {
  2451.         cannot("scroll backwards");
  2452.         sc_addline = "";
  2453.         /* Force repaint on any backward movement */
  2454.         back_scroll = 0;
  2455.     }
  2456.  
  2457.     if (dumb || tgetflag("bs"))
  2458.         sc_backspace = "\b";
  2459.     else
  2460.     {
  2461.         sc_backspace = tgetstr("bc", &sp);
  2462.         if (sc_backspace == NULL || *sc_backspace == '\0')
  2463.             sc_backspace = "\b";
  2464.     }
  2465.  
  2466.     if (couldnt)
  2467.         /* Give him time to read all the "cannot" messages. */
  2468.         error("");
  2469. }
  2470.  
  2471.  
  2472. /*
  2473.  * Below are the functions which perform all the 
  2474.  * terminal-specific screen manipulation.
  2475.  */
  2476.  
  2477.  
  2478. /*
  2479.  * Initialize terminal
  2480.  */
  2481.     public void
  2482. init()
  2483. {
  2484.     tputs(sc_init, sc_height, putc);
  2485. }
  2486.  
  2487. /*
  2488.  * Deinitialize terminal
  2489.  */
  2490.     public void
  2491. deinit()
  2492. {
  2493.     tputs(sc_deinit, sc_height, putc);
  2494. }
  2495.  
  2496. /*
  2497.  * Home cursor (move to upper left corner of screen).
  2498.  */
  2499.     public void
  2500. home()
  2501. {
  2502.     tputs(sc_home, 1, putc);
  2503. }
  2504.  
  2505. /*
  2506.  * Add a blank line (called with cursor at home).
  2507.  * Should scroll the display down.
  2508.  */
  2509.     public void
  2510. add_line()
  2511. {
  2512.     tputs(sc_addline, sc_height, putc);
  2513. }
  2514.  
  2515. /*
  2516.  * Move cursor to lower left corner of screen.
  2517.  */
  2518.     public void
  2519. lower_left()
  2520. {
  2521.     tputs(sc_lower_left, 1, putc);
  2522. }
  2523.  
  2524. /*
  2525.  * Ring the terminal bell.
  2526.  */
  2527.     public void
  2528. bell()
  2529. {
  2530.     if (quiet == VERY_QUIET)
  2531.         vbell();
  2532.     else
  2533.         putc('\7');
  2534. }
  2535.  
  2536. /*
  2537.  * Output the "visual bell", if there is one.
  2538.  */
  2539.     public void
  2540. vbell()
  2541. {
  2542.     if (*sc_visual_bell == '\0')
  2543.         return;
  2544.     tputs(sc_visual_bell, sc_height, putc);
  2545. }
  2546.  
  2547. /*
  2548.  * Clear the screen.
  2549.  */
  2550.     public void
  2551. clear()
  2552. {
  2553.     tputs(sc_clear, sc_height, putc);
  2554. }
  2555.  
  2556. /*
  2557.  * Clear from the cursor to the end of the cursor's line.
  2558.  * {{ This must not move the cursor. }}
  2559.  */
  2560.     public void
  2561. clear_eol()
  2562. {
  2563.     tputs(sc_eol_clear, 1, putc);
  2564. }
  2565.  
  2566. /*
  2567.  * Begin "standout"
  2568.  */
  2569.     public void
  2570. so_enter()
  2571. {
  2572.     tputs(sc_s_in, 1, putc);
  2573. }
  2574.  
  2575. /*
  2576.  * End "standout".
  2577.  */
  2578.     public void
  2579. so_exit()
  2580. {
  2581.     tputs(sc_s_out, 1, putc);
  2582. }
  2583.  
  2584. /*
  2585.  * Begin "underline" (hopefully real underlining, 
  2586.  * otherwise whatever the terminal provides).
  2587.  */
  2588.     public void
  2589. ul_enter()
  2590. {
  2591.     tputs(sc_u_in, 1, putc);
  2592. }
  2593.  
  2594. /*
  2595.  * End "underline".
  2596.  */
  2597.     public void
  2598. ul_exit()
  2599. {
  2600.     tputs(sc_u_out, 1, putc);
  2601. }
  2602.  
  2603. /*
  2604.  * Begin "bold"
  2605.  */
  2606.     public void
  2607. bo_enter()
  2608. {
  2609.     tputs(sc_b_in, 1, putc);
  2610. }
  2611.  
  2612. /*
  2613.  * End "bold".
  2614.  */
  2615.     public void
  2616. bo_exit()
  2617. {
  2618.     tputs(sc_b_out, 1, putc);
  2619. }
  2620.  
  2621. /*
  2622.  * Erase the character to the left of the cursor 
  2623.  * and move the cursor left.
  2624.  */
  2625.     public void
  2626. backspace()
  2627. {
  2628.     /* 
  2629.      * Try to erase the previous character by overstriking with a space.
  2630.      */
  2631.     tputs(sc_backspace, 1, putc);
  2632.     putc(' ');
  2633.     tputs(sc_backspace, 1, putc);
  2634. }
  2635.  
  2636. /*
  2637.  * Output a plain backspace, without erasing the previous char.
  2638.  */
  2639.     public void
  2640. putbs()
  2641. {
  2642.     tputs(sc_backspace, 1, putc);
  2643. }
  2644. SHAR_EOF
  2645. fi
  2646. if test -f 'signal.c'
  2647. then
  2648.     echo shar: "will not over-write existing file 'signal.c'"
  2649. else
  2650. cat << \SHAR_EOF > 'signal.c'
  2651. /*
  2652.  * Routines dealing with signals.
  2653.  *
  2654.  * A signal usually merely causes a bit to be set in the "signals" word.
  2655.  * At some convenient time, the mainline code checks to see if any
  2656.  * signals need processing by calling psignal().
  2657.  * An exception is made if we are reading from the keyboard when the
  2658.  * signal is received.  Some operating systems will simply call the
  2659.  * signal handler and NOT return from the read (with EINTR).
  2660.  * To handle this case, we service the interrupt directly from
  2661.  * the handler if we are reading from the keyboard.
  2662.  */
  2663.  
  2664. #include "less.h"
  2665. #include <signal.h>
  2666. #include <setjmp.h>
  2667.  
  2668. /*
  2669.  * The type of signal handler functions.
  2670.  * Usually int, although it should be void.
  2671.  */
  2672. typedef    int        HANDLER;
  2673.  
  2674. /*
  2675.  * "sigs" contains bits indicating signals which need to be processed.
  2676.  */
  2677. public int sigs;
  2678. #define    S_INTERRUPT    01
  2679. #ifdef SIGTSTP
  2680. #define    S_STOP        02
  2681. #endif
  2682.  
  2683. extern int reading;
  2684. extern char *first_cmd;
  2685. extern jmp_buf main_loop;
  2686.  
  2687. /*
  2688.  * Interrupt signal handler.
  2689.  */
  2690.     static HANDLER
  2691. interrupt()
  2692. {
  2693.     SIGNAL(SIGINT, interrupt);
  2694.     sigs |= S_INTERRUPT;
  2695.     if (reading)
  2696.         psignals();
  2697. }
  2698.  
  2699. #ifdef SIGTSTP
  2700. /*
  2701.  * "Stop" (^Z) signal handler.
  2702.  */
  2703.     static HANDLER
  2704. stop()
  2705. {
  2706.     SIGNAL(SIGTSTP, stop);
  2707.     sigs |= S_STOP;
  2708.     if (reading)
  2709.         psignals();
  2710. }
  2711. #endif
  2712.  
  2713. /*
  2714.  * Set up the signal handlers.
  2715.  */
  2716.     public void
  2717. init_signals()
  2718. {
  2719.     (void) SIGNAL(SIGINT, interrupt);
  2720. #ifdef SIGTSTP
  2721.     (void) SIGNAL(SIGTSTP, stop);
  2722. #endif
  2723. }
  2724.  
  2725. /*
  2726.  * Process any signals we have recieved.
  2727.  * A received signal cause a bit to be set in "sigs".
  2728.  */
  2729.     public void 
  2730. psignals()
  2731. {
  2732.     register int tsignals;
  2733.  
  2734.     tsignals = sigs;
  2735.     sigs = 0;
  2736.     if (tsignals == 0)
  2737.         return;
  2738.  
  2739.     dropout();        /* Discard any buffered output */
  2740.  
  2741. #ifdef SIGTSTP
  2742.     if (tsignals & S_STOP)
  2743.     {
  2744.         /*
  2745.          * Clean up the terminal.
  2746.          */
  2747. #ifdef SIGTTOU
  2748.         SIGNAL(SIGTTOU, SIG_IGN);
  2749. #endif
  2750.         lower_left();
  2751.         clear_eol();
  2752.         flush();
  2753.         raw_mode(0);
  2754. #ifdef SIGTTOU
  2755.         SIGNAL(SIGTTOU, SIG_DFL);
  2756. #endif
  2757.         SIGNAL(SIGTSTP, SIG_DFL);
  2758. #if SIGSETMASK
  2759.         /*
  2760.          * This system will not allow us to send a 
  2761.          * stop signal (SIGTSTP) to ourself
  2762.          * while we are in the signal handler, like maybe now.
  2763.          * (This can be the case if we are reading; see comment above.)
  2764.          * So we ask the silly system for permission to do so.
  2765.          */
  2766.         sigsetmask(0);
  2767. #endif
  2768.         kill(getpid(), SIGTSTP);
  2769.         /*
  2770.          * ... Bye bye. ...
  2771.          * Hopefully we'll be back later and resume here...
  2772.          * Reset the terminal and arrange to repaint the
  2773.          * screen when we get back to the main command loop.
  2774.          */
  2775.         SIGNAL(SIGTSTP, stop);
  2776.         raw_mode(1);
  2777.         first_cmd = "r";
  2778.         longjmp(main_loop, 1);
  2779.     }
  2780. #endif
  2781.     if (tsignals & S_INTERRUPT)
  2782.     {
  2783.         bell();
  2784.         /*
  2785.          * {{ You may wish to replace the bell() with 
  2786.          *    error("Interrupt"); }}
  2787.          */
  2788.     }
  2789.  
  2790.     longjmp(main_loop, 1);
  2791. }
  2792.  
  2793. /*
  2794.  * Pass the specified command to a shell to be executed.
  2795.  * Like plain "system()", but handles resetting terminal modes, etc.
  2796.  */
  2797.     public void
  2798. lsystem(cmd)
  2799.     char *cmd;
  2800. {
  2801.     int inp;
  2802.  
  2803.     /*
  2804.      * Print the command which is to be executed.
  2805.      */
  2806.     lower_left();
  2807.     clear_eol();
  2808.     puts("!");
  2809.     puts(cmd);
  2810.     puts("\n");
  2811.  
  2812.     /*
  2813.      * De-initialize the terminal and take out of raw mode.
  2814.      */
  2815.     deinit();
  2816.     flush();
  2817.     raw_mode(0);
  2818.  
  2819.     /*
  2820.      * Restore signals to their defaults.
  2821.      */
  2822.     SIGNAL(SIGINT, SIG_DFL);
  2823. #ifdef SIGTSTP
  2824.     SIGNAL(SIGTSTP, SIG_DFL);
  2825. #endif
  2826.     /*
  2827.      * Pass the command to the system to be executed.
  2828.      */
  2829.     inp = dup(0);
  2830.     close(0);
  2831.     open("/dev/tty", 0);
  2832.  
  2833.     system(cmd);
  2834.  
  2835.     close(0);
  2836.     dup(inp);
  2837.     close(inp);
  2838.  
  2839.     /*
  2840.      * Reset signals, raw mode, etc.
  2841.      */
  2842.     init_signals();
  2843.     raw_mode(1);
  2844.     init();
  2845. }
  2846. SHAR_EOF
  2847. fi
  2848. if test -f 'ttyin.c'
  2849. then
  2850.     echo shar: "will not over-write existing file 'ttyin.c'"
  2851. else
  2852. cat << \SHAR_EOF > 'ttyin.c'
  2853. /*
  2854.  * Routines dealing with getting input from the keyboard (i.e. from the user).
  2855.  */
  2856.  
  2857. #include "less.h"
  2858.  
  2859. /*
  2860.  * The boolean "reading" is set true or false according to whether
  2861.  * we are currently reading from the keyboard.
  2862.  * This information is used by the signal handling stuff in signal.c.
  2863.  * {{ There are probably some race conditions here
  2864.  *    involving the variable "reading". }}
  2865.  */
  2866. public int reading;
  2867.  
  2868. static int tty;
  2869.  
  2870. /*
  2871.  * Open keyboard for input.
  2872.  * (Just use file descriptor 2.)
  2873.  */
  2874.     public void
  2875. open_getc()
  2876. {
  2877.     tty = 2;
  2878. }
  2879.  
  2880. /*
  2881.  * Get a character from the keyboard.
  2882.  */
  2883.     public int
  2884. getc()
  2885. {
  2886.     char c;
  2887.     int result;
  2888.  
  2889.     reading = 1;
  2890.     do
  2891.     {
  2892.         flush();
  2893.         result = read(tty, &c, 1);
  2894.     } while (result != 1);
  2895.     reading = 0;
  2896.     return (c & 0177);
  2897. }
  2898. SHAR_EOF
  2899. fi
  2900. if test -f 'version.c'
  2901. then
  2902.     echo shar: "will not over-write existing file 'version.c'"
  2903. else
  2904. cat << \SHAR_EOF > 'version.c'
  2905. /*
  2906.  *        less
  2907.  *    Copyright (c) 1984,1985  Mark Nudelman
  2908.  *
  2909.  *    This program may be freely used and/or modified, 
  2910.  *    with the following provisions:
  2911.  *    1. This notice and the above copyright notice must remain intact.
  2912.  *    2. Neither this program, nor any modification of it,
  2913.  *       may not be sold for profit without written consent of the author.
  2914.  *
  2915.  *    -----------------------------------------------------------------
  2916.  *
  2917.  *    This program is a paginator similar to "more", 
  2918.  *    but allows you to move both forward and backward in the file.  
  2919.  *    Commands are based on "more" and "vi".
  2920.  *
  2921.  *    ----------------------- CHANGES ---------------------------------
  2922.  *
  2923.  *        Allowed use on standard input        1/29/84   markn
  2924.  *        Added E, N, P commands            2/1/84    markn
  2925.  *        Added '=' command, 'stop' signal handling    4/17/84   markn
  2926.  *        Added line folding                4/20/84   markn
  2927.  *    v2: Fixed '=' command to use BOTTOM_PLUS_ONE, 
  2928.  *        instead of TOP, added 'p' & 'v' commands    4/27/84   markn
  2929.  *    v3: Added -m and -t options, '-' command    5/3/84    markn
  2930.  *    v4: Added LESS environment variable        5/3/84    markn
  2931.  *    v5: New comments, fixed '-' command slightly    5/3/84    markn
  2932.  *    v6: Added -Q, visual bell            5/15/84   markn
  2933.  *    v7: Fixed jump_back(n) bug: n should count real
  2934.  *        lines, not folded lines.  Also allow number
  2935.  *        on G command.                5/24/84   markn
  2936.  *    v8: Re-do -q and -Q commands            5/30/84   markn
  2937.  *    v9: Added "+<cmd>" argument            9/25/84   markn
  2938.  *    v10: Fixed bug in -b<n> argument processing    10/10/84  markn
  2939.  *    v11: Made error() ring bell if \n not entered.    10/18/84  markn
  2940.  *    -----------------------------------------------------------------
  2941.  *    v12: Reorganized signal handling and made
  2942.  *         portable to 4.2bsd.            2/13/85   mark
  2943.  *    v13: Reword error message for '-' command.    2/16/85   mark
  2944.  *    v14: Added -bf and -bp variants of -b.        2/22/85   mark
  2945.  *    v15: Miscellaneous changes.            2/25/85   mark
  2946.  *    v16: Added -u flag for backspace processing.    3/13/85   mark
  2947.  *    v17: Added j and k commands, 
  2948.  *        changed -t default.            4/13/85   mark
  2949.  *    v18: Rewrote signal handling code.        4/20/85   mark
  2950.  *    v19: Got rid of "verbose" eq_message().        5/2/85    mark
  2951.  *         Made search() scroll in some cases.
  2952.  *    v20: Fixed screen.c ioctls for System V.    5/21/85   mark
  2953.  *    v21: Fixed some first_cmd bugs.            5/23/85   mark
  2954.  *    v22: Added support for no RECOMP nor REGCMP.    5/24/85   mark
  2955.  *    v23: Miscellanous changes and prettying up.    5/25/85   mark
  2956.  *      v24: Added ti,te terminal init & de-init       6/3/85 Mike Kersenbrock
  2957.  *    v25: Added -U flag, standout mode underlining.    6/8/85    mark
  2958.  *    v26: Added -M flag.                6/9/85    mark
  2959.  *         Use underline termcap (us) if it exists.
  2960.  *    v27: Renamed some variables to make unique in    6/15/85   mark
  2961.  *         6 chars.  Minor fix to -m.
  2962.  *    v28: Fixed right margin bug.            6/28/85   mark
  2963.  *    v29: Incorporated M.Rose's changes to signal.c    6/28/85   mark
  2964.  *    v30: Fixed stupid bug in argument processing.    6/29/85   mark
  2965.  *    v31: Added -p flag, changed repaint algorithm.  7/15/85   mark
  2966.  *         Added kludge for magic cookie terminals.
  2967.  *    v32: Added cat_file if output not a tty.    7/16/85   mark
  2968.  *    v33: Added -e flag and EDITOR.            7/23/85   mark
  2969.  *    v34: Added -s flag.                7/26/85   mark
  2970.  *    v35: Rewrote option handling; added option.c.    7/27/85   mark
  2971.  *    v36: Fixed -e flag to work if not last file.    7/29/85   mark
  2972.  *    v37: Added -x flag.                8/10/85   mark
  2973.  *    v38: Changed prompting; created prompt.c.    8/19/85   mark
  2974.  *    v39: (Not -p) does not initially clear screen.    8/24/85   mark
  2975.  *    v40: Added "skipping" indicator in forw().    8/26/85   mark
  2976.  *    v41: ONLY_RETURN, control char commands,    9/17/85   mark
  2977.  *         faster search, other minor fixes.
  2978.  *    v42: Added ++ command line syntax;        9/25/85   mark
  2979.  *         ch_fsize for pipes.
  2980.  *    v43: Added -h flag, changed prim.c algorithms.    10/15/85  mark
  2981.  *    v44: Made END print in all cases of eof;    10/16/85  mark
  2982.  *         ignore SIGTTOU after receiving SIGTSTP.
  2983.  *    v45: Never print backspaces unless -u.        10/16/85  mark
  2984.  *    v46: Backwards scroll in jump_loc.        10/24/85  mark
  2985.  *    v47: Fixed bug in edit(): *first_cmd==0        10/30/85  mark
  2986.  *    v48: Use TIOCSETN instead of TIOCSETP.        11/16/85  mark
  2987.  *         Added marks (m and ' commands).
  2988.  *    -----------------------------------------------------------------
  2989.  */
  2990.  
  2991. char version[] = "@(#) less  version 48";
  2992. SHAR_EOF
  2993. fi
  2994. exit 0
  2995. #    End of shell archive
  2996.  
  2997.